#pragma  once
#include <stdlib.h>
#include <vector>
#include <semaphore.h>
#include "api.hpp"
namespace server
{
  //使用数组来实现阻塞队列
  //定义一个类模板，实现我们的阻塞队列
  template<class T>
    class Block_Queue
    {
      public:
        //*************初始化阻塞队列***********************
        Block_Queue(const int capacity = 1024)
          :_data(capacity),//初始给_data开辟的空间为传过来的容量的大小
          _size(0),
          _start(0),
          _end(0)
       {
         sem_init(&sem_blanks,0,capacity);//初始的空白资源个数为capacity
         sem_init(&sem_resources,0,0);//初始的可用资源个数为0
       }

        //**************清理相关的数据************************
        ~Block_Queue()
        {
          //在析构函数中销毁信号量
          sem_destroy(&sem_blanks);
          sem_destroy(&sem_resources);
        }

        //**************实现入队列操作*************************
        void  Block_Queue_Push(const T & msg)
        {
          //将一个数据入队列，就要将空白资源个数减一
          sem_wait(&sem_blanks);

          _data[_end++] = msg;
          //printf("插入正确的信息%s\n",msg.str);
          //如果此时的_end 已经到了尾部，应该使其从下标为0开始
          if(_end >= _data.size())
          {
            _end = 0;
          }

          //将一个数据入队列后，就要将资源个数加一
          sem_post(&sem_resources);

          //实现一次入队列后，不能忘记++size
          ++_size;

          //至于为什么没有进行判断size是否大于等于_data.size()
          //是因为我们这里了的信号量已经帮我们做了这样的工作
          //假如size已经等于_data.size()了,也就是说 sem_blank 为 0,此时再进行wait时就会阻塞了
        }
        //**************实现出队列操作*************************
        void Block_Queue_Pop(T & output)
        {
          //一次出队列操作，对应的资源减一
          sem_wait(&sem_resources);

          output = _data[_start++];
          //如果此时的_start 已经到了尾部，应该使其从下标为0开始
          if(_end >= _data.size())
          if(_start == _data.size())
          {
            _start = 0;
          }

          //一次出队列操作，对应的空白数量加一
          sem_post(&sem_blanks);

          //实现一次出队列后，不能忘记--_size
          --_size;
          //至于为什么没有进行判断size是等于0
          //是因为我们这里了的信号量已经帮我们做了这样的工作
          //假如size已经等于0了,也就是说 sem_resources 为 0,此时再进行wait时就会阻塞了
        }

      private:
        //用一个vector来存放发送的消息
        std::vector<T> _data;
        size_t  _size;//用来表示当前队列中的大小
        size_t  _start;//用来表示队头 
        size_t _end;//用来表示队尾
        sem_t sem_blanks;//用来表示空着的资源的个数
        sem_t sem_resources;//用来表示可用资源的个数
        //因为只有一个消费者和一个生产者，所以没有用到互斥锁
        //sem_t _clock;//二元信号量做互斥锁，用来控制生产者和消费之之间的同步互斥关系
        
    };//end Block_Queue

}// end server namespace
